#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>


void clean_up_child_process(int signal_number)
{
	int status;
	wait(&status);
	printf("a child process is exit!\n");
	return ;
}


void register_signal_handler()
{
	struct sigaction sigchild_action;
	memset((void*)&sigchild_action, 0, sizeof(struct sigaction));
	sigchild_action.sa_handler = clean_up_child_process;
	sigaction(SIGCHLD, &sigchild_action, NULL);
}

int main(int argc, char *argv[])
{
	register_signal_handler();
	int sockfd;
	struct sockaddr_in addr;
	char buf[1024] = {0};
	memset((void*)&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(11112);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	if(sockfd==-1)
	{
		printf("create socket error!\n");
		exit(1);
	}

	int retval = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
	if(retval==-1)
	{
		printf("retval:%d\tbind error!\n", retval);
		if(errno==EBADF)
			printf("illegal socket!\n");
		else if(errno==EACCES)
			printf("auth error!\n");
		else if(errno==ENOTSOCK)
			printf("file descriptor!\n");
		printf("errno:%d\n", errno);
		close(sockfd);
		exit(1);
	}

	if(listen(sockfd, 5)==-1)
	{
		printf("listen error\n");
		close(sockfd);
		exit(1);
	}

	while(1)
	{
		struct sockaddr_in cli_addr;
		memset((void*)&cli_addr, 0, sizeof(struct sockaddr_in));
		socklen_t cli_len = sizeof(struct sockaddr);
		printf("start to accept...\n");
		int cli_sock = accept(sockfd, (struct sockaddr*)&cli_addr, &cli_len);
		printf("accept a client...\n");
		if(cli_sock==-1)
		{
			printf("accept socket error!\n");
			continue;
		}
		pid_t childpid;

		if((childpid=fork())<0)
		{
			printf("fork error!\n");
			close(cli_sock);
			continue;
		}
		else if(childpid==0)
		{
			int first = 1;
			int status = 0;
			status = fcntl(cli_sock, F_GETFL, 0);
			status |= O_NONBLOCK;
			if(fcntl(cli_sock, F_SETFL, status)==-1)
				printf("nonblock error!\n");
			
			status = fcntl(cli_sock, F_GETFL, 0);
			if(status&O_NONBLOCK)
				printf("the socket is non block!\n");
			else 
				printf("the socket is block!\n");
			
			while(1)
			{
				close(sockfd);
				int n = read(cli_sock, buf, 512);
				if(first==1)
				{
					first = 2;
					getchar();
				}
				printf("recv len:%d\n", n);
				//the connection is break
				if(strcmp(buf, "exit")==0||n==0)
				{
					close(cli_sock);
					exit(0);
				}
				//buffer is empty or signal break
				else if(n==-1)
				{
					//break by signal
					if(errno==EINTR)
						continue;
					//empty
					else if(errno==EAGAIN)
					{
						sleep(1);
						continue;
					}
					//error
					else
					{
						printf("socket is close!\n");
						exit(0);
					}
				}
				memset((void*)buf, 0, sizeof(buf));
			}
		
		}
		else
			close(cli_sock);
	
	}
	return 0;
}

